// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

package nuc98x

import (
	"openzbox.com/driver/host/distro"

	//	"openzbox.com/arch/arm/distro"
	"strings"
	"sync"
)

// Present detects whether the host CPU is an Allwinner CPU.
//
// https://en.wikipedia.org/wiki/Allwinner_Technology
func Present() bool {
	detection.do()
	return detection.isNUC980
}

/*
func Present() bool {
	if isArm {
		return strings.HasPrefix(distro.DTModel(), "NUC980")
	}
	return false
}
*/

// IsR8 detects whether the host CPU is an Allwinner R8 CPU.
//
// It looks for the string "sun5i-r8" in /proc/device-tree/compatible.
func IsDR61Y() bool {
	detection.do()
	return detection.isDR61Y
}

// IsA20 detects whether the host CPU is an Allwinner A20 CPU.
//
// It first looks for the string "sun71-a20" in /proc/device-tree/compatible,
// and if that fails it checks for "Hardware : sun7i" in /proc/cpuinfo.
func IsDK61Y() bool {
	detection.do()
	return detection.isDK61Y
}

// IsA64 detects whether the host CPU is an Allwinner A64 CPU.
//
// It looks for the string "sun50iw1p1" in /proc/device-tree/compatible.
func IsDK61YC() bool {
	detection.do()
	return detection.isDK61YC
}

//

type detectionS struct {
	mu       sync.Mutex
	done     bool
	isNUC980 bool
	isDR61Y  bool
	isDK61YC bool
	isDK61Y  bool
}

var detection detectionS

// do contains the CPU detection logic that determines whether we have an
// Allwinner CPU and if so, which exact model.
//
// Sadly there is no science behind this, it's more of a trial and error using
// as many boards and OS flavors as possible.
func (d *detectionS) do() {
	d.mu.Lock()
	defer d.mu.Unlock()
	if !d.done {
		d.done = true
		//TODO 需要结合固件判断CPU具体类型
		if isArm {
			c := distro.DTModel()
			if strings.Contains(c, "nuc980dk61yc") {
				d.isDK61YC = true
			}
			if strings.Contains(c, "nuc980dk61y") {
				d.isDK61Y = true
			}
			if strings.Contains(c, "nuc980dr61y") {
				d.isDR61Y = true
			}

			d.isNUC980 = d.isDK61YC || d.isDK61Y || d.isDR61Y

			if !d.isNUC980 {
				// The kernel in the image that comes pre-installed on the pcDuino3 Nano
				// is an old 3.x kernel that doesn't expose the device-tree in procfs,
				// so do an extra check in cpuinfo as well if we haven't detected
				// anything yet.
				// Distros based on 4.x kernels do expose it.
				if hw, ok := distro.CPUInfo()["Hardware"]; ok {
					if hw == "NUC980" {
						d.isDK61YC = true
						d.isNUC980 = true
					}
				}
			}
		}
	}
}
